import { nextTick, Ref, ref, watch } from "vue";
import { TextFontSzie } from "/@/components/common";
import type { PipePathPoint, PipePathText, Point } from "/@/components/types";
import { TextPosition } from "/@/components/types";
import {
  calc2pointDistance,
  getAngelByP1P2AndXaxis,
  getRectPointsBy2SideCenterPoint,
  getVerticalDitancePointByPoint,
  isPointInRect,
} from "/@/utils/draw";
import { buildShortUUID } from "/@/utils/uuid";

const TEXT2PATH = 6;

export interface UseTextOptions {
  points: PipePathPoint[];
  pipeSize: Ref<number>;
  innerPipeSize: Ref<number>;
}
export function usePipePathText({ points, pipeSize, innerPipeSize }: UseTextOptions) {
  const textData = ref<PipePathText[]>([]);
  /**
   * 根据给定点 找到与该点最接近的路径段
   * @param p 给定点
   * @returns 路径段起始点索引
   */
  function findPartPathByPoint(p: Point) {
    for (let i = 0; i < points.length - 1; i++) {
      const pp1 = points[i];
      const pp2 = points[i + 1];
      const { p1, p2, p3 } = getRectPointsBy2SideCenterPoint(pp1, pp2, pipeSize.value + 2);
      if (isPointInRect(p, p1, p2, p3)) {
        return i;
      }
    }
    return 0;
  }
  function getTextRefByPoint(p: Point) {
    const index = findPartPathByPoint(p);
    const p1 = points[index];
    const p2 = points[index + 1];
    if (p1.bindTextIds && p2.bindTextIds) {
      let targetTextId = "";
      for (let i = 0; i < p1.bindTextIds.length; i++) {
        if (p2.bindTextIds.indexOf(p1.bindTextIds[i]) !== -1) {
          targetTextId = p1.bindTextIds[i];
          break;
        }
      }
      return textData.value.find((el) => el.id === targetTextId);
    }
  }
  async function setTextByPoint(p: Point) {
    const index = findPartPathByPoint(p);
    const arr = [index, index + 1];
    let curText: PipePathText | undefined = textData.value.find(
      (el) => el.startIndex === arr[0] && el.endIndex === arr[1]
    );
    if (!curText) {
      const id = buildShortUUID();
      addTextIdToPoint(points[arr[0]], id);
      addTextIdToPoint(points[arr[1]], id);
      textData.value.push({
        id,
        startIndex: arr[0],
        endIndex: arr[1],
        value: "",
        width: 0,
        height: TextFontSzie,
        position: TextPosition.Top,
        editable: false,
      });
      await nextTick();
      curText = textData.value[textData.value.length - 1];
    }
    curText.editable = true;
  }
  function getTextPosition(el: PipePathText) {
    const p1 = points[el.startIndex];
    const p2 = points[el.endIndex];
    const isTop = el.position === TextPosition.Top;
    const distance = (pipeSize.value - innerPipeSize.value) / 2 + TEXT2PATH + (isTop ? el.height : 0);
    const targetP = getVerticalDitancePointByPoint(
      p1,
      p2,
      { x: (p1.x + p2.x) / 2, y: (p1.y + p2.y) / 2 },
      distance,
      isTop
    );
    return {
      transform: `rotate(${getAngelByP1P2AndXaxis(points[el.startIndex], points[el.endIndex])} ${targetP.x},${
        targetP.y
      })`,
      x: targetP.x - el.width / 2,
      y: targetP.y,
    };
  }
  function addTextIdToPoint(p: PipePathPoint, id) {
    if (!p.bindTextIds) {
      p.bindTextIds = [];
    }
    p.bindTextIds.push(id);
  }
  function removeTextId(index, key) {
    const p = points[index];
    if (p && p.bindTextIds) {
      const index = p.bindTextIds.findIndex((el) => el === key);
      if (index !== -1) {
        p.bindTextIds.splice(index, 1);
      }
    }
  }
  function delTextByIndex(index: number) {
    const p = points[index];
    if (p.bindTextIds) {
      p.bindTextIds.forEach((key) => {
        textData.value.forEach((el, j) => {
          if (el.id === key) {
            textData.value.splice(j, 1);
            return false;
          }
        });
        removeTextId(index - 1, key);
        removeTextId(index + 1, key);
      });
    }
  }

  return {
    textData,
    textHandlers: {
      findPartPathByPoint,
      setTextByPoint,
      getTextPosition,
      delTextByIndex,
      getTextRefByPoint,
    },
  };
}
